<?php

namespace App\Service\Cruise\Mission;

use App\Enums\BaseErrorCode;
use App\Enums\OpenShop\InvestmentPromotion\SiteLocationEnum;
use App\Exceptions\Custom\ResponseHttpException;
use App\Http\Middleware\OpenShop\UserPermissionAuth;
use App\Jobs\College\AutoCloseExam;
use App\Library\Rms\RmsShopApi;
use App\Models\College\CollegeTrainingOrderModel;
use App\Models\College\CollegeTrainingOrderUserModel;
use App\Models\Common\ConfigModel;
use App\Models\Cruise\CruiseCheckDetailModel;
use App\Models\Cruise\CruiseOrderExamineLogModel;
use App\Models\Cruise\CruiseOrderInputModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Cruise\CruiseOrderProcessModel;
use App\Models\Cruise\CruiseTaskProjectModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use App\Remote\Rms\RmsUserRemote;
use App\Service\BaseService;
use App\Service\Cruise\Check\CruiseCheckFsService;
use App\Service\Cruise\Check\CruiseCheckSpecialService;
use App\Service\OpenShop\Feishu\MessageSendService;
use App\Service\OpenShop\User\RmsUserService;
use App\Support\CustomForm\AttributeCruiseSupport;
use App\Support\CustomForm\AttributeSupport;
use Illuminate\Support\Facades\DB;

class CollegeInputService extends CruiseOrderInputBaseService
{
    private ?CruiseOrderModel              $cruiseOrderModel;
    private ?CollegeTrainingOrderUserModel $collegeTrainingOrderUserModel;
    private int                            $userId;

    // 理论考试及格分比例
    const EXAM_SUCCESS_RATE = 0.85;

    // 实操考试及格分
    const PRACTICE_SUCCESS_RATE = 85;

    // 考试时长
    const EXAM_DURATION = 60 * 90;

    public function __construct(int $cruiseOrderId, int $userId = 0)
    {
        $this->userId = $userId;

        $this->cruiseOrderModel = CruiseOrderModel::query()->where('id', $cruiseOrderId)->first();
        if (!$this->cruiseOrderModel) {
            BaseService::throwErr("不存在任务ID:{$cruiseOrderId}");
        }

        $this->collegeTrainingOrderUserModel = CollegeTrainingOrderUserModel::query()
                                                                            ->withoutGlobalScope('isHistory')
                                                                            ->where('cruiseOrderId',
                                                                                $this->cruiseOrderModel->id)
                                                                            ->orderByDesc('id')
                                                                            ->first();
        if (!$this->collegeTrainingOrderUserModel) {
            BaseService::throwErr('不存在用户商学院试卷');
        }

        parent::__construct($cruiseOrderId, CruiseTemplateModel::TYPE_4,
            $this->cruiseOrderModel->cruiseTemplateRel->sysTemplate ?? 0);
    }

    /**
     * 初始化表单信息
     * @return void
     */
    public function initOrderInput(bool $forceUpdate = false): void
    {
        $templateId = $this->cruiseOrderModel->templateId;
        if (!$templateId) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "获取模板类型对应模板失败:{$this->templateType}");
        }

        // 幂等-不再创建
        if (!$forceUpdate && CruiseOrderInputModel::query()->where('orderId', $this->orderId)->where('templateType', $this->templateType)->count()) {
            return;
        }

        parent::baseInitOrderInput($templateId);
    }

    /**
     * 商学院业务重写 - 初始化模板下所有项目
     * @return string
     */
    protected function initInputObjectJson(int $templateId): string
    {
        $template = CruiseTemplateModel::query()->find($templateId);
        if (!$template) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null,
                "获取模板失败:{$templateId}");
        }

        $this->projectId_field_mapping = [];

        return $template->positionsRel->map(function ($position) {

            // 单选15题、多选5题
            if ($position->name == '单选题') {
                $projectNum = 15;
            } else {
                $projectNum = 5;
            }

            // 正常状态的projects
            $projectIds = $position->positionProjectMappingsRel->pluck('projectId');
            $projectIds = CruiseTaskProjectModel::query()->whereIn('id', $projectIds)->where('status', CruiseTaskProjectModel::STATUS_ON)->pluck('id')->toArray();

            return [
                'positionName' => $position->name,
                'projects'     => $position->positionProjectMappingsRel->filter(function ($item) use ($projectIds) {
                    if (in_array($item->projectId, $projectIds)) {
                        return true;
                    }

                    return false;
                })->values()->random($projectNum)->map(function ($mapping) {
                    return $this->buildProjects($mapping);
                })->filter()->values()->toArray(),
            ];
        })->toJson(JSON_UNESCAPED_UNICODE);
    }

    public function getInputObjectFill(): array
    {
        // 提交权限
        $submit = $this->userId == $this->collegeTrainingOrderUserModel->userId;

        if ($submit && $this->cruiseOrderModel->status == CruiseOrderModel::STATUS_NOT_SUBMIT) {
            $disable = false;
        } else {
            $disable = true;
            $submit  = false;
        }

        $data                 = parent::baseGetInputObjectFill($disable);

        // 用户完成之后，答案需要回显
        if ($this->cruiseOrderModel->status == CruiseOrderModel::STATUS_COMPLETE) {

            foreach ($data['lists'] as &$projects) {
                foreach ($projects['projects'] as &$input) {
                    list($aScore, $tScore, $correctValues) = $this->calcOneInputScore($input);

                    $input['customAttributes']['correctValues'] = $correctValues;
                    $input['customAttributes']['result'] = $aScore == $tScore;
                }
            }
        }

        $data['submit']       = $submit;
        $data['status']       = $this->cruiseOrderModel->status; // 0初始化 1进行中 4已完成
        $data['needAudit']    = false;
        $data['examEndTime']  = $this->collegeTrainingOrderUserModel->examEndTime;
        $data['nowTime']      = time();
        $data['examDuration'] = self::EXAM_DURATION;

        return $data;
    }

    public function saveUserContentJson(string $field, $value): void
    {
        // 状态校验
        if ($this->cruiseOrderModel->status != CruiseOrderModel::STATUS_NOT_SUBMIT) {
            $statusText = CruiseOrderModel::CRUISE_STATUS_MAPPING[$this->cruiseOrderModel->status] ?? '';
            BaseService::throwErr("当前状态: {$statusText}，不允许修改");
        }

        // 角色校验
        if ($this->userId != $this->collegeTrainingOrderUserModel->userId) {
            BaseService::throwErr("您无权操作, 当前处理人id: {$this->collegeTrainingOrderUserModel->userId}");
        }

        parent::baseSaveUserContentJson($field, $value);
    }

    /**
     * 清空value值
     * @param bool $checkStatus
     * @return $this
     */
    public function clearValue(bool $checkStatus = true): self
    {
        if ($this->cruiseOrderModel->status == CruiseOrderModel::STATUS_INIT) {
            $this->cruiseOrderModel->status = CruiseOrderModel::STATUS_NOT_SUBMIT;
            $this->cruiseOrderModel->save();
        }

        // 状态校验
        if ($checkStatus && $this->cruiseOrderModel->status != CruiseOrderModel::STATUS_NOT_SUBMIT) {
            return $this;
        }

        $lists = $this->getInputObjectFill()['lists'];

        foreach ($lists as $list) {
            foreach ($list['projects'] as $project) {
                parent::baseSaveUserContentJson($project['field'], null);
            }
        }

        return $this;
    }

    public function submitOrder(bool $updateOrder = true): void
    {
        // 状态校验
        if ($this->cruiseOrderModel->status != CruiseOrderModel::STATUS_NOT_SUBMIT) {
            $statusText = CruiseOrderModel::CRUISE_STATUS_MAPPING[$this->cruiseOrderModel->status] ?? '';
            BaseService::throwErr("当前状态: {$statusText}，不允许修改");
        }

        // 角色校验 - 自动提交userId=0
        if ($this->userId && $this->userId != $this->collegeTrainingOrderUserModel->userId) {
            BaseService::throwErr("您无权操作, 当前处理人id: {$this->collegeTrainingOrderUserModel->userId}");
        }

        parent::baseSubmitOrder((bool)$this->userId);

        // 提交后干的事
        list($totalScore, $actualScore, $successScore, $examResult, $_) = $this->scores();

        $collegeTrainingOrderModel = CollegeTrainingOrderModel::query()
                                                                ->find($this->collegeTrainingOrderUserModel->trainingOrderId);

        DB::beginTransaction();

        $this->cruiseOrderModel->status = CruiseOrderModel::STATUS_COMPLETE;
        $this->cruiseOrderModel->save();

        $this->collegeTrainingOrderUserModel->examActualScore = $actualScore;
        $this->collegeTrainingOrderUserModel->examResult      = $examResult;
        $this->collegeTrainingOrderUserModel->save();

        // 不通过 - 整单直接改成不合格
        if ($examResult == CollegeTrainingOrderUserModel::RESULT_FAIL) {
            if ($collegeTrainingOrderModel->result == CollegeTrainingOrderModel::RESULT_INIT) {
                $collegeTrainingOrderModel->result = CollegeTrainingOrderModel::RESULT_FAIL;
                $collegeTrainingOrderModel->save();
            }
        }

        // 合格
        if ($examResult == CollegeTrainingOrderUserModel::RESULT_OK) {

            // 没有异常的人，改成初始化
            $collegeTrainingOrderModel->resetResult();
        }

        if ($updateOrder) {

            // 所有人都考完 - 改成待上传
            $checkOther = CollegeTrainingOrderUserModel::query()
                                                       ->where('trainingOrderId', $this->collegeTrainingOrderUserModel->trainingOrderId)
                                                       ->where('examResult', CollegeTrainingOrderUserModel::RESULT_INIT)
                                                       ->count();
            if ($checkOther == 0) {
                CollegeTrainingOrderModel::query()
                                         ->where('id', $this->collegeTrainingOrderUserModel->trainingOrderId)
                                         ->update(['status' => CollegeTrainingOrderModel::STATUS_WAIT_UPLOAD]);
            }
        }

        DB::commit();
    }

    public function audit(array $data): void { }

    /**
     * 开始考试
     * @return mixed
     */
    public function start(): array
    {
        // 状态校验
        if ($this->cruiseOrderModel->status != CruiseOrderModel::STATUS_INIT) {
            $statusText = CruiseOrderModel::CRUISE_STATUS_MAPPING[$this->cruiseOrderModel->status] ?? '';
            BaseService::throwErr("当前状态: {$statusText}，不允许修改");
        }

        // 角色校验
        if ($this->userId != $this->collegeTrainingOrderUserModel->userId) {
            BaseService::throwErr("您无权操作, 当前处理人id: {$this->collegeTrainingOrderUserModel->userId}");
        }

        DB::beginTransaction();
        $this->collegeTrainingOrderUserModel->examEndTime = time() + self::EXAM_DURATION;
        $this->collegeTrainingOrderUserModel->save();

        $this->cruiseOrderModel->status = CruiseOrderModel::STATUS_NOT_SUBMIT;
        $this->cruiseOrderModel->save();

        DB::commit();

        // 自动提交队列
        dispatch((new AutoCloseExam(self::EXAM_DURATION)));

        return $this->getInputObjectFill();
    }

    /**
     * 试卷基础配置
     * @return array
     */
    public function config(): array
    {
        $order = CollegeTrainingOrderModel::query()->find($this->collegeTrainingOrderUserModel->trainingOrderId);
        if (!$order) {
            BaseService::throwErr("不存在的培训id:{$this->collegeTrainingOrderUserModel->trainingOrderId}");
        }

        // 尝试修正总分
        if ($this->collegeTrainingOrderUserModel->examTotalScore == 0) {
            list($totalScore, $_, $successScore, $_, $_) = $this->scores();
            $this->collegeTrainingOrderUserModel->examTotalScore = $totalScore;
            $this->collegeTrainingOrderUserModel->save();
        } else {
            $successScore = floor($this->collegeTrainingOrderUserModel->examTotalScore * self::EXAM_SUCCESS_RATE);
        }

        return [
            'totalScore'   => $this->collegeTrainingOrderUserModel->examTotalScore,
            'successScore' => $successScore,
            'startTime'    => $order->planRel->courseStartTime ?? 0,
            'status'       => $this->cruiseOrderModel->status, // 0初始化 1进行中 4已完成
        ];
    }

    /**
     * 试卷分数情况
     * @return array
     */
    public function scores(): array
    {
        // 提交后干的事
        $inputs = $this->getInputObjectFill()['lists'];

        // 得分、总分、题数
        $actualScore = $totalScore = $questionNum = 0;

        foreach ($inputs as $input) {
            foreach ($input['projects'] as $i) {
//                if ($i['inputType'] == AttributeSupport::INPUT_TYPE_SELECT) {
//                    $options = collect($i['customAttributes']['options'])->sortByDesc('score')->keyBy('value');
//
//                    $actualScore += ($options[$i['value']]['score'] ?? 0);
//                    $totalScore  += ($options->first()['score']);
//                    $questionNum++;
//                } elseif ($i['inputType'] == AttributeSupport::INPUT_TYPE_SELECT_MULTIPLE) {
//
//                    // 当所有，有分数的项都选择了，才算得分
//                    $correctValues = collect($i['customAttributes']['options'])
//                        ->where('score', '>', 0)
//                        ->pluck('value')
//                        ->values()
//                        ->toArray();
//                    $submitValues  = is_array($i['value']) ? array_values($i['value']) : [];
//                    if ($correctValues == $submitValues) {
//
//                        foreach ($submitValues as $v) {
//                            $actualScore += (collect($i['customAttributes']['options'])
//                                    ->where('value', $v)
//                                    ->first()['score'] ?? 0);
//                        }
//                    }
//
//                    $totalScore += collect($i['customAttributes']['options'])->sum('score');
//                    $questionNum++;
//                }

                list($aScore, $tScore, $_) = $this->calcOneInputScore($i);
                $actualScore += $aScore;
                $totalScore += $tScore;
                $questionNum++;
            }
        }

        // 及格线
        $successScore = floor($totalScore * self::EXAM_SUCCESS_RATE);

        // 考试结果
        $examResult = $actualScore >= $successScore ? CollegeTrainingOrderUserModel::RESULT_OK : CollegeTrainingOrderUserModel::RESULT_FAIL;

        return [$totalScore, $actualScore, $successScore, $examResult, $questionNum];
    }
}
